#include <AutoLock.hh>
#include <DoublyNode.hh>
#include "WorkerChain.hh"

WID WorkerChain::join(Worker* NewMember)
{
	if (!State)
	{
		fprintf(stderr, "This instance(%x) is not available.\n", (Number)this);
		return RETURN_ERROR;
	}
	
	if (NewMember == NULL)
	{
		notifyError(NewMember, "Bad parameter.");
		return RETURN_PARAM_ERROR;
	}
	
	ResultOf Result;
	Node* NewNode;
	
	NewNode = createNode((void*)NewMember);
	if (NewNode == NULL)
	{
		notifyError(NewNode, "Fail createNode.");
		return InvalidId;
	}
	
	AutoLock AutoKey(LockOfIO);
	
	Result = replaceHeader(NewNode);
	if (checkError(Result))
	{
		notifyError(Result, "Fail replaceHeader.");
		return InvalidId;
	}
	
	++NumOfNode;
	return (WID)NewNode;
}

ResultOf WorkerChain::secede(WID Id)
{
	if (!State)
	{
		fprintf(stderr, "This instance(%x) is not available.\n", (Number)this);
		return RETURN_ERROR;
	}
	
	if (Id == InvalidId)
	{
		notifyError(Id, "Bad parameter.");
		return RETURN_PARAM_ERROR;
	}
	
	Node* MemberNode;
	MemberNode = (Node*)Id;
	
	ResultOf Result;
	{
		AutoLock AutoKey(LockOfIO);
		
		if (MemberNode == Header)
		{
			Result = updateHeader();
			checkErrorWR(Result, "Fail updateHeader.");
		}
		else if (MemberNode == Tail)
		{
			Result = updateTail();
			checkErrorWR(Result, "Fail updateTail.");
		}
		
		--NumOfNode;
		
		Result = MemberNode->unlink();
		checkErrorWR(Result, "Fail MemberNode->unlink.");
	}
	
	delete MemberNode;
	return RETURN_OK;
}

Worker* WorkerChain::ban()
{
	if (!State)
	{
		fprintf(stderr, "This instance(%x) is not available.\n", (Number)this);
		return InvalidId;
	}
	
	return (Worker*)removeTail();
}

USNumber WorkerChain::tellSize()
{
	if (!State)
	{
		fprintf(stderr, "This instance(%x) is not available.\n", (Number)this);
		return 0;
	}
	
	return NumOfNode;
}
